Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Objects /
Chapter 2 - Shape Objects / Using Shape Objects


Drawing and Hit-Testing Shapes

Drawing and hit-testing are common actions you may perform with any kind of shape. The most basic QuickDraw GX drawing function is GXDrawShape, although there are other functions for drawing specific types of shapes. Only GXDrawShape is described here.

The functions you use for hit-testing are GXHitTestShape, GXHitTestPicture, GXHitTestLayout, and GXHitTestDevice. Only GXHitTestShape is described here.

Drawing Shapes

Drawing a shape is the logical conclusion to creating it and setting its properties. Drawing occurs in the view port or view ports specified in the transform object associated with the shape. Drawing takes into account all the information in the shape's transform, ink, style, and shape objects.

What it means to draw a specific type of shape and how changing the information in a shape alters its drawn appearance is described, along with each type of shape, in Inside Macintosh: QuickDraw GX Graphics and Inside Macintosh: QuickDraw GX Typography. Furthermore, for many shape types, QuickDraw GX provides specialized drawing functions, such as GXDrawLine and GXDrawGlyphs--described in those books--that allow you to create, draw, and dispose of an object with a single call.

At its most basic, though, creating and drawing a shape is as simple as the following listing for creating and drawing a path shape shows:

gxShape myShape;                    /* allocate the variable */
myShape = GXNewShape(gxPathType);   /* create the shape */
.  
.                                   /* set its properties */
.
GXDrawShape(myShape);               /* draw it */
The GXDrawShape function is described on page 2-84.

Hit-Testing Shapes

Hit-testing converts a coordinate location to a shape-geometry location. It can give you feedback on user actions involving a shape you have drawn. For example, you use hit-testing to select a shape the user has clicked the mouse over, to select a point within a shape, or to position the insertion point and draw the caret within the text of a typographic shape.

QuickDraw GX provides a general hit-testing function for all shapes, plus specialized functions for hit-testing picture shapes, layout shapes, and pixels on a display device:

When you hit-test a shape with GXHitTestShape, you must first set up the shape parts mask and the tolerance, two components of the hit-test parameters property of a shape's transform object. You pass that information to GXHitTestShape, and QuickDraw GX returns information in the hit-test info structure.

The tolerance is a distance (in units of geometry space), and it defines a circular area centered on the hit point. Any part that falls within that area is considered to correspond to the hit point.

Shape Parts

When you use GXHitTestShape, it returns one or more shape parts, which specify the parts of the shape's geometry corresponding to the hit point. The parts of a shape's geometry for which you can hit-test depend on the kind of shape. The shape parts that you can test for are defined in the gxShapeParts enumeration. Before calling GXHitTestShape, you set up, in the transform object, a mask of all the shape parts that you want to test for. GXHitTestShape can test only for parts that you specify in the shape parts mask. These are the possible values to put into the mask:

enum gxShapeParts {      /* (in order of evaluation) */
   gxNoPart             = 0,   
   gxBoundsPart         = 0x0001,
   gxGeometryPart       = 0x0002,
   gxPenPart            = 0x0004,
   gxCornerPointPart    = 0x0008,
   gxControlPointPart   = 0x0010,
   gxEdgePart           = 0x0020,
   gxJoinPart           = 0x0040,
   gxStartCapPart       = 0x0080,
   gxEndCapPart         = 0x0100,
   gxDashPart           = 0x0200,
   gxPatternPart        = 0x0400,
   gxGlyphBoundsPart    = gxJoinPart,
   gxGlyphFirstPart     = gxStartCapPart,
   gxGlyphLastPart      = gxEndCapPart,
   gxSideBearingPart    = gxDashPart,
   gxAnyPart            = gxBoundsPart | gxGeometryPart | 
            gxPenPart | gxCornerPointPart | gxControlPointPart | 
            gxEdgePart | gxJoinPart | gxStartCapPart | 
            gxEndCapPart | gxDashPart | gxPatternPart
} ;

typedef long gxShapePart;
These values are described in more detail in the chapter "Transform Objects" in this book. Note that values specifying join, cap, and dash parts in geometric shapes are used in typographic shapes to specify various glyph parts. Note also that you can specify no parts or all parts in the mask. You decide which shape parts are appropriate for your needs.

Hit-Test Info Structure

When you call GXHitTestShape, it returns some information as a function result and other information in a hit-test info structure. The first three fields of the hit-test info structure give all the relevant information about the hit:

struct gxHitTestInfo {
   gxShapePart    what;
   long           index;
   Fixed          distance;
   gxShape        which;
   gxShape        containerPicture;
   long           containerIndex;
   long           totalIndex;
};
The what field tells you which shape parts out of those specified in your mask were hit, if any. It is identical to the GXHitTestShape function result.

The index field tells you the index number of the point in the geometry that is closest to the hit point.

The distance field tells you how far, in geometry coordinates, the hit point is from the first shape part that was hit. GXHitTestShape analyzes shape parts in a specific order--the order listed in the gxShapeParts enumeration. By carefully specifying shape parts, you can use GXHitTestShape to obtain specific distance information for a given part. For example, if you are hit-testing a line like that shown in Figure 2-5 on page 2-21, you can determine the distance from the hit point to the pen if you exclude both bounds and geometry from the test.

The remaining fields in the hit-test info structure are not used by GXHitTestShape.

Hit-Testing Example

Listing 2-2 uses hit-testing to determine whether a point (aPoint) is contained in the geometry that represents a shape (gShape). The code sets up a shape-part mask (mask) specifying that only the geometry it to be tested for, and calls the GXSetShapeHitTest function to assign the mask, plus a tolerance of zero, to the shape's transform.

Listing 2-2 Hit-testing a line

gxShape        pointShape;
gxPoint        aPoint = {ff(50), ff(51)};
gxShapePart    mask = gxGeometryPart;
gxShapePart    resultMask;
gxHitTestInfo  resultInfo;

pointShape = GXNewPoint(&aPoint);
GXSetShapeHitTest(gShape, mask, ff(0));
resultMask = GXHitTestShape(gShape, &aPoint, &resultInfo);
GXDisposeShape(pointShape);
The function result from GXHitTestShape tells which part of the shape was hit. Because only one part (gxGeometryPart) is specified and tolerance is 0, a successful hit is possible only if aPoint is actually within the geometry of the shape.

In the event of a successful hit, GXHitTestShape also fills in a gxHitTestInfo structure (resultInfo parameter) that contains additional information about the hit.

The gxHitTestInfo structure is described on page 2-50. The GXHitTestShape function is described on page 2-86. Because the shape parts to test against are specified
in a shape's transform object, the list of defined QuickDraw GX shape parts, and the GXSetShapeHitTest function, are described in the chapter "Transform Objects" in
this book.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996